package com.photoeditor.demo.ui.widget.beauty;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

import com.android.util.OpenCVHelper;
import com.common.base.ComponentContext;
import com.common.base.log.DLog;
import com.common.base.utils.DeviceUtils;
import com.photoeditor.demo.ui.widget.LoadingView;
import com.photoeditor.demo.ui.widget.image.attacher.CanvasPhotoViewAttacher;
import com.photoeditor.demo.ui.widget.image.attacher.IPhotoView;
import com.photoeditor.demo.util.AsyncTask;
import com.photoeditor.demo.util.ImageRectUtils;
import com.photoeditor.demo.util.beauty.WarpControl;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by winn on 17/7/14.
 */

public class RepairView extends ImageView implements IPhotoView {
    private boolean mIsInDeal;
    private int mTouchOutSideBoundsWidth = DeviceUtils.dip2px(ComponentContext.getContext(), 2);
    private int mEffectStep = 0;
    private LoadingView mProgressDialog;
    private IStatusListener mStatusListener;
    private CanvasPhotoViewAttacher mAttacher;
    private List<History> mHistoryList;
    private final static float MAX_TOUCH_SIZE = DeviceUtils.dip2px(ComponentContext.getContext(), 120);
    private Bitmap mSrcBitmap;
    private Bitmap mOriginalBitmap;
    private Bitmap mCurEffectBitmap;
    private float mCurX;
    private float mCurY;
    private int MAX_RADIUS_PROGRESS = DeviceUtils.dip2px(ComponentContext.getContext(), 12.0F);
    private int MIN_RADIUS_PROGRESS = DeviceUtils.dip2px(ComponentContext.getContext(), 4.0F);
    // 触摸点范围
    private Rect mEffectRect;
    private float mEffectRectCenterX;
    private float mEffectRectCenterY;

    private int mTouchMode = MODE_NONE;
    private final static int MODE_NONE = 0;
    private final static int MODE_EFFECT = 1;

    private boolean mIsInit;

    /**
     * 初始化后显示的Drawable
     */
    private RectF mSupportDrawableRect;
    /**
     * 这个是图片的Bounds Drawable
     */
    private RectF mBaseDrawableRect;
    //本界面的Bound Rect
    private RectF mRect;
    //Drawable的Bound Rect  默认
    private RectF mDrawableRect;
    //用于显示当前 点击位置的
    private RectF mTouchRect;
    private Rect mTcouchSrcRect;
    private RectF mCacheRect;
    private float mTouchSize;
    private boolean mTouchIsInLeft = true;

    //是否绘制中间的圆
    private boolean mDrawCenterCircle = false;
    //是否当前位置的圆
    private boolean mDrawCurrentCircle = false;
    private float mCurRadius = (MAX_RADIUS_PROGRESS - MIN_RADIUS_PROGRESS) / 2 + MIN_RADIUS_PROGRESS;

    private Paint mRingPaint;
    private Paint mCirclePaint;
    private Paint mCenterPaint;
    private Paint mCommonPaint;
    private Paint mTouchOutSidePaint;

    private IRepairListener mOperationListener;

    private CanvasPhotoViewAttacher.OnMatrixChangedListener mMatrixChangeListener = new CanvasPhotoViewAttacher.OnMatrixChangedListener() {
        @Override
        public void onMatrixChanged(RectF rect) {
            if (mDrawableRect == null) {
                mDrawableRect = new RectF();
            }
            mDrawableRect.set(rect);
            mTouchSize = Math.min(mDrawableRect.width(), MAX_TOUCH_SIZE);
            mTouchSize = Math.min(mDrawableRect.height(), mTouchSize);
            if (mTouchIsInLeft) {
                mTouchRect.set(0, 0, mTouchSize, mTouchSize);
                mTouchRect.offset(mTouchOutSideBoundsWidth, mTouchOutSideBoundsWidth);
            } else {
                mTouchRect.set(mRect.width() - mTouchSize, 0, mRect.width(), mTouchSize);
                mTouchRect.offset(-mTouchOutSideBoundsWidth, -mTouchOutSideBoundsWidth);
            }
        }
    };

    public RepairView(Context context) {
        this(context, null);
    }

    public RepairView(Context context, @Nullable AttributeSet attributeSet) {
        this(context, attributeSet, 0);
        initialize(context);
    }

    public RepairView(Context paramContext, @Nullable AttributeSet attributeSet, int defStyleAttr) {
        super(paramContext, attributeSet, defStyleAttr);
        super.setScaleType(ImageView.ScaleType.MATRIX);
        mAttacher = new CanvasPhotoViewAttacher(this);
        setOnMatrixChangeListener(mMatrixChangeListener);
    }

    private void initialize(Context context) {
        setWillNotDraw(false);
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        setMaximumScale(8.0f);
        setMediumScale(1.0f);
        mHistoryList = new ArrayList<>();
        mRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mRingPaint.setStyle(Paint.Style.STROKE);
        mRingPaint.setColor(Color.WHITE);
        mRingPaint.setStrokeWidth(DeviceUtils.dip2px(ComponentContext.getContext(), 2));

        mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCirclePaint.setStyle(Paint.Style.FILL);
        mCirclePaint.setColor(Color.parseColor("#33000000"));

        mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCenterPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mCenterPaint.setColor(Color.WHITE);
        mCenterPaint.setStrokeCap(Paint.Cap.ROUND);
        mCenterPaint.setStrokeJoin(Paint.Join.ROUND);

        mCommonPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);

        mTouchOutSidePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTouchOutSidePaint.setStyle(Paint.Style.STROKE);
        mTouchOutSidePaint.setColor(Color.WHITE);
        mTouchOutSidePaint.setStrokeWidth(mTouchOutSideBoundsWidth * 2);

        mTouchRect = new RectF();
        mTcouchSrcRect = new Rect();
        mCacheRect = new RectF();
        mEffectRect = new Rect();
    }

    public void init(RectF rect) {
        if (!mIsInit) {
            mRect = rect;
            countDrawableInitPosition(rect);
            mBaseDrawableRect = new RectF(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
            mTouchSize = Math.min(mBaseDrawableRect.width(), MAX_TOUCH_SIZE);
            mTouchSize = Math.min(mBaseDrawableRect.height(), mTouchSize);
            mTouchRect.set(0, 0, mTouchSize, mTouchSize);
            mTouchRect.offset(mTouchOutSideBoundsWidth, mTouchOutSideBoundsWidth);
            mTouchIsInLeft = true;
            mIsInit = true;
        }
    }

    private void doRepair(Bitmap repairBitmap) {
        float radius = getCurRadius();
        float radiusSq = (float) (radius * 0.95D * radius * 0.95D);
        int[] arrayOfInt = new int[repairBitmap.getWidth() * repairBitmap.getHeight()];
        int y = 0;
        int width = repairBitmap.getWidth();
        while (y < repairBitmap.getHeight()) {
            int x = 0;
            while (x < repairBitmap.getWidth()) {
                if ((x - mEffectRectCenterX) * (x - mEffectRectCenterX) + (y - mEffectRectCenterY) * (y - mEffectRectCenterY) <= radiusSq) {
                    arrayOfInt[(width * y + x)] = 0xffffffff;
                } else {
                    arrayOfInt[(width * y + x)] = 0;
                }
                x += 1;
            }
            y += 1;
        }

        int w = repairBitmap.getWidth();
        int h = repairBitmap.getHeight();

        Bitmap maskBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        maskBitmap.setPixels(arrayOfInt, 0, w, 0, 0, w, h);

        mCurEffectBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

        try {
            long time = System.currentTimeMillis();
            DLog.i("winn", "time start");
            OpenCVHelper.inpaint(repairBitmap, maskBitmap, mCurEffectBitmap, w, h, 5.0D, 1);
            DLog.i("winn", "time:" + (System.currentTimeMillis() - time));
        } catch (Exception e) {
            mCurEffectBitmap = repairBitmap;
        } catch (UnsatisfiedLinkError error) {
            mCurEffectBitmap = repairBitmap;
        }
    }

    private void pushHistory() {
        this.mEffectStep += 1;
        if (mHistoryList.size() >= 3)
            mHistoryList.remove(0);
        Bitmap bitmap = this.mCurEffectBitmap.copy(Bitmap.Config.ARGB_8888, false);
        History history = new History(new Rect(this.mEffectRect.left, this.mEffectRect.top,
                this.mEffectRect.right, this.mEffectRect.bottom), bitmap);
        mHistoryList.add(history);
    }

    private float getCurRadius() {
        float scale = mBaseDrawableRect.width() / mDrawableRect.width();
        return mCurRadius * scale;
    }

    @Override
    public boolean canZoom() {
        return mAttacher.canZoom();
    }

    @Override
    public float getBaseScale() {
        return mAttacher.getBaseScale();
    }

    public Bitmap getCurBitmap() {
        if (mSrcBitmap != null) {
            return mSrcBitmap;
        }
        return mOriginalBitmap;
    }

    @Override
    public Matrix getDisplayMatrix() {
        return mAttacher.getDisplayMatrix();
    }

    @Override
    public RectF getDisplayRect() {
        return mAttacher.getDisplayRect();
    }

    @Override
    public IPhotoView getIPhotoViewImplementation() {
        return mAttacher;
    }

    @Deprecated
    public float getMaxScale() {
        return getMaximumScale();
    }

    @Override
    public float getMaximumScale() {
        return mAttacher.getMaximumScale();
    }

    @Override
    public float getMediumScale() {
        return mAttacher.getMediumScale();
    }

    @Override
    @Deprecated
    public float getMidScale() {
        return getMediumScale();
    }

    @Override
    @Deprecated
    public float getMinScale() {
        return getMinimumScale();
    }

    @Override
    public float getMinimumScale() {
        return mAttacher.getMinimumScale();
    }

    @Override
    public CanvasPhotoViewAttacher.OnPhotoTapListener getOnPhotoTapListener() {
        return mAttacher.getOnPhotoTapListener();
    }

    @Override
    public CanvasPhotoViewAttacher.OnViewTapListener getOnViewTapListener() {
        return mAttacher.getOnViewTapListener();
    }

    @Override
    public float getScale() {
        return mAttacher.getScale();
    }

    @Override
    public ImageView.ScaleType getScaleType() {
        return mAttacher.getScaleType();
    }

    @Override
    public Bitmap getVisibleRectangleBitmap() {
        return mAttacher.getVisibleRectangleBitmap();
    }

    /**
     * 是否改变
     *
     * @return
     */
    public boolean isChanged() {
        return mHistoryList.size() != 0;
    }

    @Override
    protected void onDetachedFromWindow() {
        mAttacher.cleanup();
        super.onDetachedFromWindow();
    }

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (!mIsInit || mSrcBitmap == null || mSrcBitmap.isRecycled()) {
            return;
        }

        int saveCount = canvas.save();
        float centerX = Math.max(mDrawableRect.left, mCurX);
        centerX = Math.min(mDrawableRect.right, centerX);
        float centerY = Math.max(mDrawableRect.top, mCurY);
        centerY = Math.min(mDrawableRect.bottom, centerY);

        canvas.clipRect(mDrawableRect);//裁剪到当前显示区域内

        if (mDrawCenterCircle) {
            mCacheRect.set(mRect);
            mCacheRect.offset(-mRect.left, -mRect.top);
            drawCircleFlag(canvas, mCacheRect.centerX(), mCacheRect.centerY());
        }

        if (mDrawCurrentCircle) {
            drawCircleFlag(canvas, centerX, centerY);
        }
        canvas.restoreToCount(saveCount);
        if (mDrawCurrentCircle) {
            int saveCount2 = canvas.save();
            if (mTouchRect.contains(centerX, centerY)) {
                if (mTouchIsInLeft) {
                    mTouchIsInLeft = false;
                    mTouchRect.set(mRect.width() - mTouchSize, 0, mRect.width(), mTouchSize);
                    mTouchRect.offset(-mTouchOutSideBoundsWidth, -mTouchOutSideBoundsWidth);
                } else {
                    mTouchIsInLeft = true;
                    mTouchRect.set(0, 0, mTouchSize, mTouchSize);
                    mTouchRect.offset(mTouchOutSideBoundsWidth, mTouchOutSideBoundsWidth);
                }
            }
            canvas.clipRect(mTouchRect.left - mTouchOutSideBoundsWidth, mTouchRect.top - mTouchOutSideBoundsWidth
                    , mTouchRect.right + mTouchOutSideBoundsWidth, mTouchRect.bottom + mTouchOutSideBoundsWidth);//裁剪到当前显示区域内
            float radius = mTouchSize / 2;
            mCacheRect.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
            float dx = 0, dy = 0;//下面的代码用于保证框内一定会显示完全
            if (mCacheRect.left < mDrawableRect.left) {
                dx = mDrawableRect.left - mCacheRect.left;
            } else if (mCacheRect.right > mDrawableRect.right) {
                dx = mDrawableRect.right - mCacheRect.right;
            }
            if (mCacheRect.top < mDrawableRect.top) {
                dy = mDrawableRect.top - mCacheRect.top;
            } else if (mCacheRect.bottom > mDrawableRect.bottom) {
                dy = mDrawableRect.bottom - mCacheRect.bottom;
            }
            mCacheRect.offset(dx, dy);
            //这个touchCenterX touchCenterY就是小图中的中心点
            float touchCenterX = mTouchRect.centerX() - dx;
            float touchCenterY = mTouchRect.centerY() - dy;

            float scale = mDrawableRect.width() / mBaseDrawableRect.width();
            mCacheRect.offset(-mDrawableRect.left, -mDrawableRect.top);
            mTcouchSrcRect.set((int) (mCacheRect.left / scale), (int) (mCacheRect.top / scale), (int) (mCacheRect.right / scale), (int) (mCacheRect.bottom / scale));
            canvas.drawBitmap(mSrcBitmap, mTcouchSrcRect, mTouchRect, mCommonPaint);
            drawCircleFlag(canvas, touchCenterX, touchCenterY);
            canvas.drawRect(mTouchRect.left - mTouchOutSideBoundsWidth, mTouchRect.top - mTouchOutSideBoundsWidth
                    , mTouchRect.right + mTouchOutSideBoundsWidth, mTouchRect.bottom + mTouchOutSideBoundsWidth, mTouchOutSidePaint);
            canvas.restoreToCount(saveCount2);
        }
    }

    protected void onLayout(boolean paramBoolean, int paramInt1, int paramInt2, int paramInt3, int paramInt4) {
        super.onLayout(paramBoolean, paramInt1, paramInt2, paramInt3, paramInt4);
        if (!mIsInit && mSrcBitmap != null && !mSrcBitmap.isRecycled()) {
            init(ImageRectUtils.getViewRect(this));
        }
    }

    /**
     * @param canvas
     * @param centerX
     * @param centerY
     */
    private void drawCircleFlag(Canvas canvas, float centerX, float centerY) {//保证一定绘制在内部
        canvas.drawCircle(centerX, centerY, mCurRadius, mCirclePaint);
        canvas.drawCircle(centerX, centerY, mCurRadius, mRingPaint);
    }

    public boolean onTouchEvent(MotionEvent event) {
        if (!mIsInit || mIsInDeal) return super.onTouchEvent(event);
        if (event.getPointerCount() != 1) {
            setDrawCurrentCircle(false);
            mAttacher.onTouch(this, event);
            mTouchMode = MODE_NONE;
        } else {//单指点击的
            WarpControl curBean = new WarpControl();
            int action = event.getAction();
            if (action == MotionEvent.ACTION_DOWN) {
                mCurX = event.getX();
                mCurY = event.getY();
                if (isTouchInImage(mCurX, mCurY)) {
                    mTouchMode = MODE_EFFECT;
                    setDrawCurrentCircle(true);
                }
                mAttacher.onTouch(this, event);
                return true;
            } else if (action == MotionEvent.ACTION_MOVE) {
                mCurX = event.getX();
                mCurY = event.getY();
                if (mTouchMode == MODE_EFFECT) {
                    if (isTouchInImage(mCurX, mCurY)) {
                        setDrawCurrentCircle(true);
                    } else {
                        setDrawCurrentCircle(false);
                    }
                    invalidate();
                } else {
                    mAttacher.onTouch(this, event);
                }
            } else if (action == MotionEvent.ACTION_UP) {
                setDrawCurrentCircle(false);
                if (mTouchMode == MODE_EFFECT) {
                    mCurX = event.getX();
                    mCurY = event.getY();
                    float scale = mBaseDrawableRect.width() / mDrawableRect.width();
                    int x = (int) ((mCurX - mDrawableRect.left) * scale);
                    int y = (int) ((mCurY - mDrawableRect.top) * scale);
                    curBean.orig_x = x;
                    curBean.orig_y = y;
                    curBean.max_dist = getCurRadius();
                    curBean.max_dist_sq = curBean.max_dist * curBean.max_dist;
                    mEffectRect.left = (int) (x - curBean.max_dist);
                    mEffectRect.right = (int) (x + curBean.max_dist);
                    mEffectRect.top = (int) (y - curBean.max_dist);
                    mEffectRect.bottom = (int) (y + curBean.max_dist);
                    mEffectRectCenterX = mEffectRect.width() / 2;
                    mEffectRectCenterY = mEffectRect.height() / 2;
                    // 确保区域在图片范围内
                    if (mEffectRect.left < 0) {
                        mEffectRect.left = 0;
                    }
                    if (mEffectRect.top < 0) {
                        mEffectRect.top = 0;
                    }
                    if (mEffectRect.right > mBaseDrawableRect.width()) {
                        mEffectRect.right = (int) mBaseDrawableRect.width();
                    }
                    if (mEffectRect.bottom > mBaseDrawableRect.height()) {
                        mEffectRect.right = (int) mBaseDrawableRect.height();
                    }
                    if (isTouchInImage(mCurX, mCurY) && mEffectRect.width() > 0 && mEffectRect.height() > 0) {
                        doEffect();
                    }
                } else {
                    mAttacher.onTouch(this, event);
                }
                mTouchMode = MODE_NONE;
            } else {
                mTouchMode = MODE_NONE;
                setDrawCurrentCircle(false);
                mAttacher.onTouch(this, event);
            }
        }
        return super.onTouchEvent(event);
    }

    private boolean isTouchInImage(float x, float y) {
        boolean ret = false;
        if (mSupportDrawableRect.contains(x, y)) {
            ret = true;
        }
        return ret;
    }

    private void doEffect() {
        if (mIsInDeal) {
            return;
        }
        mIsInDeal = true;
        if (mProgressDialog != null) {
            mProgressDialog.startLoading();
        }
        AsyncTask.DUAL_THREAD_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                // 点击区域范围
                int width = mEffectRect.width();
                int height = mEffectRect.height();
                Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                mCurEffectBitmap = bitmap;
                Canvas canvas = new Canvas(mCurEffectBitmap);
                RectF rectF = new RectF(0, 0, width, height);
                // 取出需要修复的区域图像
                canvas.drawBitmap(mSrcBitmap, mEffectRect, rectF, mCommonPaint);
                pushHistory();

                doRepair(bitmap);
                // 修复后的图像重新绘制回原图
                Canvas srcCanvas = new Canvas(mSrcBitmap);
                srcCanvas.drawBitmap(mCurEffectBitmap, new Rect(0, 0, width, height),
                        mEffectRect, mCommonPaint);
                post(new Runnable() {
                    @Override
                    public void run() {
                        onDealOver();
                    }
                });
            }
        });
    }

    /**
     * 处理完成后
     */
    private void onDealOver() {
        setImageBitmap(mSrcBitmap, false);
        mProgressDialog.stopLoading();
        mIsInDeal = false;
        notifyListener();
    }

    public void setProgressDialog(LoadingView progressDialog) {
        mProgressDialog = progressDialog;
    }

    /**
     * 清除所有的
     */
    public void reset() {
        if (mOriginalBitmap != null && !mOriginalBitmap.isRecycled()) {
            mOriginalBitmap.recycle();
        }
        mOriginalBitmap = null;
        setImageBitmap(null);
        mHistoryList.clear();
        this.mEffectStep = 0;
        notifyListener();
    }

    @Override
    public void setAllowParentInterceptOnEdge(boolean allow) {
        mAttacher.setAllowParentInterceptOnEdge(allow);
    }

    @Override
    public boolean setDisplayMatrix(Matrix finalRectangle) {
        return mAttacher.setDisplayMatrix(finalRectangle);
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        setImageBitmap(bm, false);
    }

    /**
     * @param bm
     * @param updateMatrix 是否重置当前的Matrix
     */
    public void setImageBitmap(Bitmap bm, boolean updateMatrix) {
        super.setImageBitmap(bm);
        if (bm != null) {
            mSrcBitmap = bm.copy(Bitmap.Config.ARGB_8888, true);
        }
        if ((updateMatrix) && (mAttacher != null)) {
            mAttacher.update();
        }
    }

    @Override
    public void setImageResource(int resId) {
        super.setImageResource(resId);
        if (null != mAttacher) {
            mAttacher.update();
        }
    }

    @Override
    public void setImageURI(Uri uri) {
        super.setImageURI(uri);
        if (null != mAttacher) {
            mAttacher.update();
        }
    }

    @Override
    @Deprecated
    public void setMaxScale(float maxScale) {
        setMaximumScale(maxScale);
    }

    @Override
    public void setMaximumScale(float maximumScale) {
        mAttacher.setMaximumScale(maximumScale);
    }

    @Override
    public void setMediumScale(float mediumScale) {
        mAttacher.setMediumScale(mediumScale);
    }

    @Override
    @Deprecated
    public void setMidScale(float midScale) {
        setMediumScale(midScale);
    }

    @Deprecated
    public void setMinScale(float minScale) {
        setMinimumScale(minScale);
    }

    @Override
    public void setMinimumScale(float minimumScale) {
        mAttacher.setMinimumScale(minimumScale);
    }

    @Override
    public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener newOnDoubleTapListener) {
        mAttacher.setOnDoubleTapListener(newOnDoubleTapListener);
    }

    @Override
    public void setOnLongClickListener(OnLongClickListener l) {
        mAttacher.setOnLongClickListener(l);
    }

    @Override
    public void setOnMatrixChangeListener(CanvasPhotoViewAttacher.OnMatrixChangedListener listener) {
        mAttacher.setOnMatrixChangeListener(listener);
    }

    @Override
    public void setOnPhotoTapListener(CanvasPhotoViewAttacher.OnPhotoTapListener listener) {
        mAttacher.setOnPhotoTapListener(listener);
    }

    @Override
    public void setOnViewTapListener(CanvasPhotoViewAttacher.OnViewTapListener listener) {
        mAttacher.setOnViewTapListener(listener);
    }

    /**
     * 设置原图
     */
    public void setOriginalBitmap(Bitmap paramBitmap) {
        mOriginalBitmap = paramBitmap.copy(Bitmap.Config.ARGB_8888, false);
    }

    @Override
    public void setPhotoViewRotation(float rotationDegree) {
        mAttacher.setRotationTo(rotationDegree);
    }

    @Override
    public void setRotationBy(float rotationDegree) {
        mAttacher.setRotationBy(rotationDegree);
    }

    @Override
    public void setRotationTo(float rotationDegree) {
        mAttacher.setRotationTo(rotationDegree);
    }

    @Override
    public void setScale(float scale) {
        mAttacher.setScale(scale);
    }

    @Override
    public void setScale(float scale, float focalX, float focalY, boolean animate) {
        mAttacher.setScale(scale, focalX, focalY, animate);
    }

    @Override
    public void setScale(float scale, boolean animate) {
        mAttacher.setScale(scale, animate);
    }

    @Override
    public void setScaleType(ScaleType scaleType) {
        if (null != mAttacher) {
            mAttacher.setScaleType(scaleType);
        }
    }

    /**
     * 0 - 100
     *
     * @param progress
     */
    public void setProgress(int progress) {
        mCurRadius = progress / 100f * (MAX_RADIUS_PROGRESS - MIN_RADIUS_PROGRESS) + MIN_RADIUS_PROGRESS;
        invalidate();
    }

    public void setDrawCenterCircle(boolean drawCircle) {
        mDrawCenterCircle = drawCircle;
        invalidate();
    }

    public void setDrawCurrentCircle(boolean drawCurrentCircle) {
        this.mDrawCurrentCircle = drawCurrentCircle;
        if (mStatusListener != null) {
            mStatusListener.onStatusChanged(drawCurrentCircle);
        }
        invalidate();
    }

    public void setStatusListener(IStatusListener listener) {
        mStatusListener = listener;
    }

    public void setZoomTransitionDuration(int paramInt) {
        mAttacher.setZoomTransitionDuration(paramInt);
    }

    @Override
    public void setZoomable(boolean zoomable) {
        mAttacher.setZoomable(zoomable);
    }

    public void showEffect() {
        setImageBitmap(mSrcBitmap);
    }

    public void showOriginalBitmap() {
        super.setImageBitmap(mOriginalBitmap);
    }

    public void undo() {
        if (mHistoryList.size() > 0) {
            mIsInDeal = true;
            History history = mHistoryList.remove(mHistoryList.size() - 1);
            new Canvas(mSrcBitmap).drawBitmap(history.getBitmap(), new Rect(0, 0, history.getRect().width(), history.getRect().height()),
                    history.getRect(), mCommonPaint);
            setImageBitmap(mSrcBitmap);
            mIsInDeal = false;
            notifyListener();
        }
    }

    class History {
        private Rect mRect;
        private Bitmap mBitmap;

        public History(Rect rect, Bitmap bitmap) {
            mRect = rect;
            mBitmap = bitmap;
        }

        public Rect getRect() {
            return mRect;
        }

        public Bitmap getBitmap() {
            return mBitmap;
        }
    }

    /**
     * 这个方法要在Init后调用
     */
    private void countDrawableInitPosition(RectF viewRect) {
        mSupportDrawableRect = new RectF();
        float width = mSrcBitmap.getWidth();
        float height = mSrcBitmap.getHeight();

        float vW = viewRect.width();
        float vH = viewRect.height();

        float w, h;

        if (width / height > vW / vH) {//宽顶着
            w = vW;
            h = w / width * height;
        } else {//高顶着
            h = vH;
            w = h / height * width;
        }

        mSupportDrawableRect.left = (vW - w) / 2 + viewRect.left;
        mSupportDrawableRect.top = (vH - h) / 2 + viewRect.top;
        mSupportDrawableRect.right = mSupportDrawableRect.left + w;
        mSupportDrawableRect.bottom = mSupportDrawableRect.top + h;
    }

    private void notifyListener() {
        if (mOperationListener != null) {
            mOperationListener.onOperationSizeChanged(mHistoryList.size(), mEffectStep);
        }
    }

    public void setOperationListener(IRepairListener operationListener) {
        this.mOperationListener = operationListener;
    }

    public interface IRepairListener {
        void onOperationSizeChanged(int historySize, int effectStep);
    }
}
